package cn.xzqwjw.taskmanager.utils;

import cn.hutool.core.util.ArrayUtil;
import cn.xzqwjw.taskmanager.common.customEnum.ResponseCodeEnum;
import cn.xzqwjw.taskmanager.common.exception.CustomException;
import cn.xzqwjw.taskmanager.domain.vo.UploadConfigVo;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import net.coobird.thumbnailator.name.Rename;
import net.coobird.thumbnailator.resizers.configurations.ScalingMode;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.util.Objects;

/**
 * 生成缩略图、水印、选择、格式转换
 * 具体帮助文档 https://github.com/coobird/thumbnailator/wiki/Maven
 */
public class ThumbUtil {

  /**
   * 生成指定大小的缩略图，并将缩略图保存在指定位置
   * size(width,height) 若图片横比200小，高比300小，不变
   * 若图片横比200小，高比300大，高缩小到300，图片比例不变
   * 若图片横比200大，高比300小，横缩小到200，图片比例不变
   * 若图片横比200大，高比300大，图片按比例缩小，横为200或高为300
   */
  public static void setThumbBySize(UploadConfigVo configDto, Integer width, Integer height) {
    try {
      Thumbnails
          .of(configDto.getServerFileNameEntire())
          .size(width, height)
          // 图片质量压缩90%
          .outputQuality(configDto.getCompressRatio())
          // 转换格式
          .outputFormat("jpg")
          .toFile(new File(configDto.getThumb1FileNameEntire()));
    } catch (IOException e) {
      throw new CustomException(ResponseCodeEnum.ERROR_DRAW_THUMB);
    }
  }

  /**
   * 按比例、压缩率等生成缩略图，并将缩略图保存在指定位置
   */
  public static void setThumbByScale(UploadConfigVo configDto, Double scale) {
    try {
      Thumbnails
          .of(configDto.getServerFileNameEntire())
          // 图片缩放80%, 不能和size()一起使用
          .scalingMode(ScalingMode.BICUBIC)
          .scale(scale)
          // 压缩质量80%
          .outputQuality(configDto.getCompressRatio())
          // 转换格式
          .outputFormat("jpg")
          .toFile(new File(configDto.getThumb1FileNameEntire()));
    } catch (IOException e) {
      throw new CustomException(ResponseCodeEnum.ERROR_DRAW_THUMB);
    }
  }

  /**
   * 将指定目录下所有图片生成缩略图
   */
  public static void setThumbDirectory(String dirName, Double scale, Double compress) {
    File[] files = new File(dirName).listFiles();
    if (Objects.isNull(files) || ArrayUtil.isEmpty(files)) {
      return;
    }
    try {
      Thumbnails
          .of(files)
          .scalingMode(ScalingMode.BICUBIC)
          // 图片缩放80%, 不能和size()一起使用
          .scale(scale)
          // 压缩质量80%
          .outputQuality(compress)
          // 转换格式
          .outputFormat("jpg")
          // 指定的目录一定要存在,否则报错
          .toFiles(new File(dirName), Rename.SUFFIX_HYPHEN_THUMBNAIL);
    } catch (IOException e) {
      throw new CustomException(ResponseCodeEnum.ERROR_DRAW_THUMB);
    }
  }

  /**
   * 对图片加文字水印
   *
   * @param configDto 系统设置对象
   */
  public static void drawWmTxt(UploadConfigVo configDto) {
    try {
      BufferedImage bi = new BufferedImage(160, 160, BufferedImage.TYPE_INT_ARGB);
      Graphics2D g = bi.createGraphics();
      g.setColor(Color.decode(configDto.getWaterMarkTxtColor()));
      g.drawRect(0, 0, 10, 10);
      char[] wmTxt = configDto.getWaterMarkTxtString().toCharArray();
      g.drawChars(wmTxt, 0, wmTxt.length, 20, 20);
      Thumbnails.of(configDto.getServerFileNameEntire())
          .scale(1.0f)
          // 图片质量压缩80%
          .outputQuality(configDto.getCompressRatio())
          // 转换格式
          .outputFormat("jpg")
          .watermark(Positions.BOTTOM_RIGHT, bi, configDto.getWaterMarkTransparent())
          .toFile(configDto.getServerFileNameEntireWithWm());
    } catch (IOException ex) {
      throw new CustomException(ResponseCodeEnum.ERROR_DRAW_WM_TXT);
    }
  }

  /**
   * 对图片加图片水印
   *
   * @param configDto 系统设置对象
   */
  public static void drawWmImg(UploadConfigVo configDto) {
    try {
      Thumbnails
          .of(configDto.getServerFileNameEntire())
          .scale(1.0f)
          // 图片质量压缩80%
          .outputQuality(configDto.getCompressRatio())
          // 转换格式
          .outputFormat("jpg")
          .watermark(Positions.BOTTOM_RIGHT,
              ImageIO.read(new File(getWmImg(configDto))),
              configDto.getWaterMarkTransparent())
          .toFile(configDto.getServerFileNameEntireWithWm());
    } catch (IOException ex) {
      throw new CustomException(ResponseCodeEnum.ERROR_DRAW_WM_IMG);
    }
  }

  /**
   * 从系统配置里得到水印图片文件的完整服务器端的路径+文件名
   */
  private static String getWmImg(UploadConfigVo configDto) {
    URL url = UldlUtil.class.getClassLoader().getResource(configDto.getWaterMarkImagePath());
    if (Objects.isNull(url)) {
      return "";
    } else {
      String result = url.getFile().substring(1);
      System.out.println("getWmImgEntirePath()打印出水印图片文件的路径+文件名：" + result);
      return result;
    }
  }

  /**
   * 指定大小进行缩放
   */
  public static void scaleBySize(String source, String dest) throws IOException {
    /*
     * size(width,height) 若图片横比200小，高比300小，不变
     * 若图片横比200小，高比300大，高缩小到300，图片比例不变
     * 若图片横比200大，高比300小，横缩小到200，图片比例不变
     * 若图片横比200大，高比300大，图片按比例缩小，横为200或高为300
     */
    Thumbnails.of(source).size(200, 300).toFile(dest);
  }

  /**
   * 按照比例进行缩放
   */
  public static void scaleByAspect(String source, String dest) throws IOException {
    Thumbnails.of(source).scale(0.25f).toFile(dest);
    Thumbnails.of(source).scale(1.10f).toFile(dest);
  }

  /**
   * 不按照比例，指定大小进行强制缩放
   */
  public static void scaleByFixedSize(String source, String dest) throws IOException {
    // keepAspectRatio(false) 默认是按照比例缩放的
    Thumbnails.of(source)
        .size(120, 120)
        .keepAspectRatio(false)
        .toFile(dest);
  }

  /**
   * 旋转
   */
  public static void rotate(String source, String dest) throws IOException {
    // rotate(角度) 正数：顺时针 负数：逆时针
    Thumbnails.of(source).size(1280, 1024).rotate(90).toFile(dest);
    Thumbnails.of(source).size(1280, 1024).rotate(-90).toFile(dest);
  }

  /**
   * 水印
   */
  public static void addWm(String source, String dest, String wmImg) throws IOException {
    // watermark(位置，水印图，透明度)
    Thumbnails.of(source)
        .size(1280, 1024)
        .watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File(wmImg)), 0.5f)
        .outputQuality(0.8f)
        .toFile(dest);
    Thumbnails.of(source)
        .size(1280, 1024)
        .watermark(Positions.CENTER, ImageIO.read(new File(wmImg)), 0.5f)
        .outputQuality(0.8f)
        .toFile(dest);
  }

  /**
   * 裁剪
   */
  public static void cut(String source, String dest) throws IOException {
    // 图片中心400*400的区域
    Thumbnails.of(source)
        .sourceRegion(Positions.CENTER, 400, 400)
        .size(200, 200)
        .keepAspectRatio(false)
        .toFile(dest);
    // 图片右下400*400的区域
    Thumbnails.of(source)
        .sourceRegion(Positions.BOTTOM_RIGHT, 400, 400)
        .size(200, 200)
        .keepAspectRatio(false)
        .toFile(dest);
    // 指定坐标
    Thumbnails.of(source)
        .sourceRegion(600, 500, 400, 400)
        .size(200, 200)
        .keepAspectRatio(false)
        .toFile(dest);
  }

  /**
   * 转化图像格式
   */
  public static void transfer(String source, String dest) throws IOException {
    // outputFormat(图像格式)
    Thumbnails.of(source).size(1280, 1024).outputFormat("png").toFile(dest);
    Thumbnails.of(source).size(1280, 1024).outputFormat("gif").toFile(dest);
  }

  /**
   * 输出到OutputStream
   */
  public static void toOpStream(String source, String dest) throws IOException {
    // toOutputStream(流对象)
    OutputStream os = new FileOutputStream(dest);
    Thumbnails.of(source).size(1280, 1024).toOutputStream(os);
  }

  /**
   * 输出到BufferedImage
   */
  public static void toBufferImage(String source, String dest) throws IOException {
    // asBufferedImage() 返回BufferedImage
    BufferedImage thumb = Thumbnails.of(source).size(1280, 1024).asBufferedImage();
    ImageIO.write(thumb, "jpg", new File(dest));
  }

}
